package tools

import (
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/h2non/filetype"
	"io"
	"os"
	"path/filepath"
)

func FileWrites(filename string, content []byte) error {

	path := filepath.Dir(filename)
	if _, err := os.Stat(path); os.IsNotExist(err) {
		if err = os.MkdirAll(path, 0755); err != nil {
			return errors.New(fmt.Sprintf("创建目录失败：%v", err))
		}
	}

	files, err := os.OpenFile(filename, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666)
	if err != nil {
		return errors.New(fmt.Sprintf("打开文件写入失败:%v", err))
	}

	defer files.Close()

	if _, err = files.Write(content); err != nil {
		return errors.New(fmt.Sprintf("写入文件失败: %v", err))
	}
	return nil
}

func FileExists(filename string) bool {
	fmt.Println(filename)
	file, err := os.OpenFile("./"+filename, os.O_RDONLY, 0666)
	if err != nil {
		return false
	}

	defer file.Close()
	return true
}

func FileRead(filename string) ([]byte, error) {
	file, err := os.OpenFile(filename, os.O_RDONLY, 0666)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("打开文件失败:%v", err))
	}
	defer file.Close()
	return io.ReadAll(file)
}

func FileDelete(filename string) error {
	if is := FileExists(filename); is {
		if err := os.Remove(filename); err != nil {
			return errors.New(fmt.Sprintf("删除文件失败:%v", err))
		}
	}
	return nil
}

func FileToMd5(filePath string) (string, error) {
	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		return "", errors.New(fmt.Sprintf("文件打开失败:", err))
	}
	defer file.Close()

	// 初始化MD5哈希器
	hasher := md5.New()

	// 复制文件内容到哈希器，同时检查任何读取错误
	if _, err := io.Copy(hasher, file); err != nil {
		return "", errors.New(fmt.Sprintf("文件复制失败:", err))
	}

	// 计算MD5哈希值并格式化为十六进制字符串
	md5Hash := fmt.Sprintf("%x", hasher.Sum(nil))
	return md5Hash, nil
}

func File(filePath string) (*FileData, error) {
	file, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("打开文件失败:%v", err))
	}
	defer file.Close()
	bytes, err := io.ReadAll(file)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("读取文件失败:%v", err))
	}

	// 初始化MD5哈希器
	hasher := md5.New()

	// 复制文件内容到哈希器，同时检查任何读取错误
	if _, err := io.Copy(hasher, file); err != nil {
		return nil, errors.New(fmt.Sprintf("文件复制失败:", err))
	}

	// 计算MD5哈希值并格式化为十六进制字符串
	md5Hash := fmt.Sprintf("%x", hasher.Sum(nil))

	match, err := filetype.Match(bytes)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("识别文件失败:%v", err))
	}

	mimetype := "application/octet-stream"

	if match.Extension != "unknown" {
		mimetype = match.MIME.Value
	}

	fileInfo, err := os.Stat(filePath)
	if err != nil {
		return nil, err
	}

	return &FileData{
		fileInfo,
		mimetype,
		md5Hash,
	}, nil
}

type FileData struct {
	Info     os.FileInfo `json:"info"`
	MimeType string      `json:"mimetype"`
	Md5Hash  string      `json:"md5_hash"`
}
